package com.apacheGzq.http;
import org.apache.commons.lang.StringUtils;

import com.apacheGzq.constant.Constants;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by gaozhiqiang .
 */
public class SimpleHttpRequestImpl implements HttpRequest {

    private String requestMsg;
    private String requestMethod;
    private String requestUri;
    private String protocolVersion;
    private String host;
    private String serverName;
    private int serverPort;
    private String remoteAddr;
    private String encoding;
    private String queryString;
    private Map<String, String> requestHeader = new HashMap<String, String>();
    private Map<String, Object> requestParamter = new HashMap<String, Object>();
    private Map<String, Object> requestAttribute = new HashMap<String, Object>();

    public SimpleHttpRequestImpl() {}

    public SimpleHttpRequestImpl(String requestMsg) {
        this.requestMsg = requestMsg;
    }

    private void parseHeader() {
        int startPosition=0, endPosition=0, msgLength=0;
        if(StringUtils.isEmpty(requestMsg)) {
            return;
        }
        msgLength = requestMsg.length();

        Field[] fields = HttpRequest.class.getDeclaredFields();
        String fieldName = null, tmpStr=null;
        for(Field field : fields) {
            try {
                fieldName = (String) field.get(HttpRequest.class);
                startPosition = requestMsg.indexOf(fieldName);
                endPosition = requestMsg.indexOf(Constants.CRLF, startPosition);

                if(0 <= startPosition && startPosition <= endPosition && endPosition <= msgLength) {
                    tmpStr = requestMsg.substring(startPosition, endPosition);
                    if(StringUtils.isNotEmpty(tmpStr) && tmpStr.contains(":")) {
                        startPosition = tmpStr.indexOf(":")+1;
                        if(0<=startPosition&&startPosition<=tmpStr.length()) {
                            requestHeader.put(fieldName, tmpStr.substring(startPosition).trim());
                        }
                    }
                }

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
    }

    private void parseParameter() {
        if("GET".equalsIgnoreCase(requestMethod)) {
            if(StringUtils.isNotEmpty(queryString)) {
                String[] paramStrArr = queryString.split("&");
                for(String tmpStr : paramStrArr) {
                    String[] paramKeyValues = tmpStr.split("=");
                    this.requestParamter.put(paramKeyValues[0], paramKeyValues[1]);
                }
            }
        } else if("POST".equalsIgnoreCase(requestMethod)) {
            int startPosition=requestMsg.indexOf(Constants.CRLF+Constants.CRLF);
            if(0<=startPosition && startPosition <= requestMsg.length()) {
                String paramStr = requestMsg.substring(startPosition+4);
                if(StringUtils.isNotEmpty(paramStr) && paramStr.contains("=")) {
                    String[] paramStrArr = paramStr.split("&");
                    for(String tmpStr : paramStrArr) {
                        String[] paramKeyValues = tmpStr.split("=");
                        this.requestParamter.put(paramKeyValues[0], paramKeyValues[1]);
                    }
                }
            }
        }
    }

    @Override
    public void parserRequest(String request) {
        int startPosition=0, endPosition=0, msgLength=0;
        if(StringUtils.isEmpty(requestMsg)) {
            if(StringUtils.isNotEmpty(request)) {
                this.requestMsg = request;
            } else {
                return;
            }
        }
        msgLength = requestMsg.length();
        endPosition = requestMsg.indexOf(" ");
        if(endPosition>0 && endPosition <= msgLength) {
            requestMethod = requestMsg.substring(startPosition, endPosition);
        }
        startPosition = endPosition+1;
        endPosition = requestMsg.indexOf(" ", startPosition);
        if(endPosition>0 && endPosition <= msgLength) {
            requestUri = requestMsg.substring(startPosition, endPosition);
            if("GET".equalsIgnoreCase(requestMethod) && requestUri.contains("?")) {
                int tmpPosition = requestUri.indexOf("?");
                queryString = requestUri.substring(tmpPosition);
                requestUri = requestUri.substring(0, tmpPosition);
            } else {
                queryString = "";
            }
        }

        startPosition = endPosition+1;
        endPosition = requestMsg.indexOf(Constants.CRLF, startPosition);
        if(endPosition>0 && endPosition <= msgLength) {
            protocolVersion = requestMsg.substring(startPosition, endPosition);
        }

        //host
        startPosition = requestMsg.indexOf(HttpRequest.HOST);
        endPosition = requestMsg.indexOf(Constants.CRLF, startPosition);
        if(endPosition>0 && endPosition <= msgLength) {
            host = requestMsg.substring(startPosition, endPosition);
            startPosition = host.indexOf(" ");
            if(startPosition <= endPosition) {
                host = host.substring(startPosition);

                if(host.contains(":")) {
                    String[] tmpArr = host.split(":");
                    serverName = tmpArr[0];
                    serverPort = Integer.valueOf(tmpArr[1]);
                } else {
                    serverName = host;
                    serverPort = 80;
                }
            }
        }

        parseHeader();
        parseParameter();

    }

    @Override
    public String getMethod() {
        return requestMethod;
    }

    @Override
    public String getRequestUri() {
        return requestUri;
    }

    @Override
    public String getRequestUrl() {
        return this.getScheme() + "://"+this.getHost()+this.getRequestUri();
    }

    @Override
    public String getScheme() {
        return Constants.SCHEME;
    }

    @Override
    public String getServerName() {
        return serverName;
    }

    @Override
    public int getServerPort() {
        return serverPort;
    }

    @Override
    public String getHost() {
        return host;
    }

    @Override
    public String setRemoteAddr(String remoteAddr) {
        return this.remoteAddr = remoteAddr;
    }

    @Override
    public String getRemoteAddr() {
        return remoteAddr;
    }

    @Override
    public String getQueryString() {
        return queryString;
    }

    @Override
    public String getParameter(String name) {
        return null;
    }

    @Override
    public String getHeader(String name) {
        return this.requestHeader.get(name);
    }

    @Override
    public Object getAttribute(String name) {
        return this.requestAttribute.get(name);
    }

    @Override
    public void setAttribute(String name, Object object) {
        this.requestAttribute.put(name, object);
    }

    @Override
    public String setCharacterEncoding(String encodingName) {
        return this.encoding = encodingName;
    }

    @Override
    public String getCharacterEncoding() {
        return this.encoding;
    }

    @Override
    public String getProtocolVersion() {
        return protocolVersion;
    }

    @Override
    public boolean isAllowMethod() {
        return this.getMethod().equalsIgnoreCase("GET")||this.getMethod().equalsIgnoreCase("POST");
    }

    @Override
    public boolean isImplemented() {
        return this.getMethod().equalsIgnoreCase("GET")||this.getMethod().equalsIgnoreCase("POST");
    }

}

